/*--------------------------------------------------------------*                                       
 *--------------------------------------------------------------*/

#ifndef _EXT_BLOCK_LOG_H_
#define _EXT_BLOCK_LOG_H_

#include <stdint.h>
#include "rtctime.h"
#include "log_buff_manage.h"

#define FLASH_BLOCK_ERR_NONE         0
#define FLASH_BLOCK_ERR_PAGE_SIZE    1  /*扇区尺寸错误*/
#define FLASH_BLOCK_ERR_BLOCK_SIZE   2  /*BLOCK尺寸错误*/
#define FLASH_BLOCK_ERR_BLOCK_NUMS   3
#define FLASH_BLOCK_ERR_SIZE         4  /*实际数据个数*/
#define FLASH_BLOCK_ERR_PAG_PER_BLK  5  /*基址错误,基址未对齐到扇区边界*/
#define FLASH_BLOCK_ERR_LOG_SIZE     6  /*数据尺寸大于eep尺寸*/

typedef struct
{
	int32_t page;
	int16_t site_offset;
	int16_t addr_offset;
} block_log_site_type;

typedef struct{
    uint32_t block_next;			/*指向当前准备写入的块位置， 相对base的位置*/
    uint32_t block_start;			/*数据起始块地址， 相对base的位置*/
	uint32_t page_next;
    uint16_t Err;					/*上次错误代码*/
    uint8_t Checked;				/*参数已经通过检测*/
	uint8_t full;					/*数据已经存满，继续存储将开始覆盖式写入*/
} block_log_info_type;

typedef struct {
	uint32_t block_base;			/*起始块逻辑号*/
    uint16_t block_amount;			/*总块数*/
    uint16_t page_per_block;		/*每块页数*/
    uint16_t page_size;				/*页面尺寸，字节数 */
	uint16_t log_size;				/*每条日志尺寸，用于搜索位置*/
    block_log_info_type *Info;		/*运行时信息*/
    void (*Erase)(uint32_t block_addr);		/*从指定地址擦除*/
    void (*Program)(uint32_t block_addr);	/*向指定指定地址编程数据*/
    void (*Read)(uint32_t page, uint16_t offset, uint16_t Len, uint8_t *Data);	/*从指定位置读取数据*/
} block_log_cfg_type;

uint16_t block_log_check(const block_log_cfg_type *Cfg);
uint16_t block_log_save(const block_log_cfg_type *Cfg);

// page_des返回页的相对位置
uint16_t block_log_head_search(const block_log_cfg_type *Cfg, uint32_t num, uint32_t *page_des);

/*-----------------------------------------------------------------------------------------------------*
 * 快速搜索，内部采用二分搜索法，从start到next-1区间
 * mode: 0(未命中目标时返回-1)，-1(未命中目标时返回小于目标值的位置)，1(未命中目标时返回大于目标值的位置)
 * return 返回-1代表未搜到指定结果
 * 	site_des = site.page * (cfg->page_size / cfg->log_size) + site.site_offset;
 *-----------------------------------------------------------------------------------------------------*/
int32_t block_log_time_search(const block_log_cfg_type * Cfg, sig_time_type time, int8_t mode);

///////////////////////////////////////////////////////////////////////////////////////////////////////////
typedef  struct 
{
	const block_log_cfg_type *blk;
	const log_buff_cfg_type *buf;
} block_log_mix_type;

// 结果如果在主存区，按site编址的位置
// 结果如果在buff区，buff内的位置
int32_t block_log_mix_time_search(const block_log_mix_type *cfg, sig_time_type time, int8_t mode);

// 标量位置转为buff位置，如果不在buff区，返回-1
int32_t block_log_asite_to_lsite(const block_log_cfg_type *cfg, block_log_site_type site );
block_log_site_type block_log_lsite_to_asite(const block_log_cfg_type *cfg, int32_t site );
int32_t block_log_site_amount(const block_log_cfg_type *cfg,  int32_t site_start, int32_t site_end);

int8_t block_log_mix_site_check(const block_log_mix_type *cfg,  int32_t site );
int32_t block_log_mix_site_inc(const block_log_mix_type *cfg,  int32_t site, int32_t inc);
int32_t block_log_mix_read(const block_log_mix_type *cfg,  int32_t site, int16_t len_max, void *buff);

#endif
